package com.xy.job.admin.core

import com.xy.job.admin.common.config.LocalDateTimeSerializer
import com.xy.job.core.api.request.JobKillParam
import com.xy.job.core.api.request.JobLogParam
import com.xy.job.core.api.request.JobTriggerParam
import com.xy.job.core.api.response.ResponseWrapper
import io.ktor.client.*
import io.ktor.client.call.*
import io.ktor.client.engine.cio.*
import io.ktor.client.plugins.*
import io.ktor.client.plugins.contentnegotiation.*
import io.ktor.client.plugins.logging.*
import io.ktor.client.request.*
import io.ktor.http.*
import io.ktor.serialization.kotlinx.json.*
import kotlinx.coroutines.runBlocking
import kotlinx.serialization.json.Json
import kotlinx.serialization.modules.SerializersModule
import java.time.LocalDateTime

class ExecutorClient(
    private val host: String,
    private val port: Int,
) {

    private val jsonConfig = Json {
        serializersModule = SerializersModule {
            contextual(LocalDateTime::class, LocalDateTimeSerializer)
        }
        ignoreUnknownKeys = true
    }

    private val client: HttpClient = HttpClient(CIO) {
        expectSuccess = true
        install(Logging) {
            this.level = LogLevel.NONE
        }
        // TODO: 配置化
        install(HttpTimeout) {
            this.connectTimeoutMillis = 2000L
            this.socketTimeoutMillis = 2000L
            this.requestTimeoutMillis = 5000L
        }
        install(ContentNegotiation) {
            json(jsonConfig)
        }
        defaultRequest {
            host = this@ExecutorClient.host
            port = this@ExecutorClient.port
        }
    }

    fun trigger(param: JobTriggerParam): ResponseWrapper<Boolean> {
        return runBlocking {
            val result = client.post("/private/job/trigger") {
                contentType(ContentType.Application.Json)
                setBody(param)
            }
            result.body()
        }
    }

    fun kill(param: JobKillParam): ResponseWrapper<Boolean> {
        return runBlocking {
            val result = client.post("/private/job/kill") {
                contentType(ContentType.Application.Json)
                setBody(param)
            }
            result.body()
        }
    }

    fun log(param: JobLogParam): ResponseWrapper<String> {
        return runBlocking {
            val result = client.post("/private/job/log") {
                contentType(ContentType.Application.Json)
                setBody(param)
            }
            result.body()
        }
    }

}